package com.chengzhi.structure;

import java.util.TreeMap;

/**
 * @description: trie
 * @author: ruanchengzhi
 * @create: 2020-03-14 15:24
 **/
public class Trie {


    private Node root;

    private int size;

    public Trie() {
        root = new Node();
        size = 0;
    }

    /**
     * 添加单词 递归实现
     *
     * @param word
     * @return: void
     * @author: ruanchengzhi
     * @date: 2020/5/8
     */
    public void add(String word) {
        Node cur = root;
        add(cur, word, 0);
    }

    private void add(Node cur, String word, int index) {
        if (!cur.isWord && word.length() == index) {
            cur.isWord = true;
            size++;
        }
        if (word.length() > index) {
            char c = word.charAt(index);
            if (cur.next.get(c) == null) {
                cur.next.put(c, new Node());
            }
            add(cur.next.get(c), word, index + 1);
        }
    }

    /**
     * 是否包含单词 递归实现
     *
     * @param word
     * @return: boolean
     * @author: ruanchengzhi
     * @date: 2020/5/8
     */
    public boolean contains(String word) {
        Node cur = root;
        return contains(cur, word, 0);
    }

    private boolean contains(Node cur, String word, int index) {
        if (word.length() == index) {
            return cur.isWord;
        }
        char c = word.charAt(index);
        if (cur.next.get(c) == null) {
            return false;
        } else {
            return contains(cur.next.get(c), word, index + 1);
        }
    }

    /**
     * 是否包含开始的数据 递归实现
     *
     * @param prefix
     * @return: boolean
     * @author: ruanchengzhi
     * @date: 2020/5/8
     */
    public boolean containsPreFix(String prefix) {
        Node cur = root;
        return containsPreFix(cur, prefix, 0);
    }

    private boolean containsPreFix(Node cur, String prefix, int index) {
        if (prefix.length() == index) {
            return true;
        }
        char c = prefix.charAt(index);
        if (cur.next.get(c) == null) {
            return false;
        } else {
            return containsPreFix(cur.next.get(c), prefix, index + 1);
        }
    }

    /**
     * 插入 循环实现
     *
     * @param word
     * @return: void
     * @author: ruanchengzhi
     * @date: 2020/5/8
     */
    public void insert(String word) {
        Node cur = root;
        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            if (cur.next.get(c) == null) {
                cur.next.put(c, new Node());
            }
            cur = cur.next.get(c);
        }
        if (!cur.isWord) {
            cur.isWord = true;
            size++;
        }
    }

    /**
     * 查找 循环时间
     *
     * @param word
     * @return: boolean
     * @author: ruanchengzhi
     * @date: 2020/5/8
     */
    public boolean search(String word) {
        Node cur = root;
        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            if (!cur.next.containsKey(c)) {
                return false;
            }
            cur = cur.next.get(c);
        }
        return cur.isWord;
    }

    /**
     * 以什么开头 循环实现
     *
     * @param prefix
     * @return: boolean
     * @author: ruanchengzhi
     * @date: 2020/5/8
     */
    public boolean startsWith(String prefix) {
        Node cur = root;
        for (int i = 0; i < prefix.length(); i++) {
            char c = prefix.charAt(i);
            if (!cur.next.containsKey(c)) {
                return false;
            }
            cur = cur.next.get(c);
        }
        return true;
    }


    private class Node {
        private boolean isWord;

        private TreeMap<Character, Node> next;

        public Node() {
            this.isWord = false;
            this.next = new TreeMap<>();
        }

        public boolean isWord() {
            return isWord;
        }
    }
}
